# import urllib
from urllib import request
from urllib import parse
import time
import json
import configparser
from Config import ConfigController
from Logger import Logger
from Email import Email


# 发送模版消息的类，不过会有文件资源占用的问题
class WechatApi:
	def __init__(self, configFile="../Config/config.ini", logFile='../Logger/logging.json'):
		# self.emailController = Email.EmailController()
		self.__configPath = configFile
		self.__loggerConfigPath = logFile
		self.config = ConfigController.ConfigController(configFile=self.__configPath, logFile=self.__loggerConfigPath)
		self.__appID = self.config.getConfig(sectionName="WECHAT",
											 optionName="APP_ID")
		self.__appSecret = self.config.getConfig(sectionName="WECHAT",
												 optionName="APP_SECRET")
		self.__accessTokenUrl = self.config.getConfig(sectionName="WECHAT",
													  optionName='ACCESS_TOKEN_URL')
		self.__grantType = self.config.getConfig(sectionName="WECHAT",
												 optionName="GRANT_TYPE")
		self.__accessToken = ''
		self.__lastRequire = time.time()
		self.__urlData = parse.urlencode({
			"grant_type": self.__grantType,
			"appid": self.__appID,
			"secret": self.__appSecret
		})
		self.logger = Logger.Logger(self.__loggerConfigPath)

	# 获取接口调用凭证，刷新token和有效期
	def getAccessToken(self):
		accessToken = self.config.getConfig(sectionName='WECHAT',
											optionName='ACCESS_TOKEN')
		validTime = float(self.config.getConfig(sectionName='WECHAT',
												optionName='TOKEN_VALID_TIME'))
		lastRequired = float(self.config.getConfig(sectionName='WECHAT',
												   optionName='TOKEN_LAST_REQUIRED'))
		# 两次调用获取token的间隔如果超过了token的有效期，刷新token
		if self.isAccessTokenOutOfDate(validTime, lastRequired):
			url = self.__accessTokenUrl + self.__urlData
			httpRequest = request.Request(url)
			httpResponse = request.urlopen(httpRequest)
			returnSource = httpResponse.read().decode('utf-8')
			returnJson = json.loads(returnSource)

			# 如果调用微信API接口出现了问题
			if returnJson.get('errcode', False):
				self.logger.fileInfoLogger.error(returnJson.get('errmsg', ""))
				return False

			# 如果成功返回access_token，刷新配置文件
			else:
				accessToken = returnJson['access_token']
				self.config.setConfig(sectionName='WECHAT',
									  optionName='ACCESS_TOKEN',
									  value=accessToken)
				self.config.setConfig(sectionName='WECHAT',
									  optionName='TOKEN_VALID_TIME',
									  value=str(returnJson['expires_in']))
				self.config.setConfig(sectionName='WECHAT',
									  optionName='TOKEN_LAST_REQUIRED',
									  value=str(time.time()))
				# 保存配置文件
				if self.config.saveConfig(self.__configPath):
					self.logger.fileInfoLogger.info(
						'Required access token %s, valid in %s s' % (accessToken, str(returnJson['expires_in'])))
				else:
					self.logger.fileInfoLogger.error('Save config file failed. Maybe file system error.')
					emailController = Email.EmailController()
					emailController.sendEmail(msgStr="获取接口调用凭证时出错，保存配置文件失败！位于Api.py line74 ", subject="保存配置文件失败！",
											  withLog=False)
					return None

		# 两次调用没有超过token的有效期，不刷新 / 刷新完毕，返回刷新后的token
		return accessToken

	# 获取所有模版列表
	def getAllTemplate(self):
		token = self.__accessToken
		url = "https://api.weixin.qq.com/cgi-bin/template/get_all_private_template?access_token=%s" % (token)
		httpRequest = request.Request(url)
		httpResponse = request.urlopen(httpRequest)
		responseSource = httpResponse.read().decode('utf-8')
		responseJson = json.loads(responseSource)
		if responseJson.get('errcode', False):
			self.logger.fileInfoLogger.error("Time: %f, with error: %s" % (time.time(), responseJson.get('errmsg', "")))
			return False
		else:
			templist = responseJson['template_list']
			return templist

	def sendOnLineNotice(self, userID, openID, data,
						 url="http://weixin.qq.com/download",
						 templateID="IbUPQdkCezcDvat-hCiVHTJrj947P0vVKG4SPxhQmBg"):
		userID = userID
		postData = json.dumps({
			'touser': openID,
			'template_id': templateID,
			'url': url,
			'data': data
		}).encode("utf-8")
		url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s" % (self.getAccessToken())
		httpRequest = request.Request(url)
		httpResponse = request.urlopen(httpRequest, data=postData)
		responseSource = httpResponse.read().decode('utf-8')
		responseJson = json.loads(responseSource)
		print(responseSource)
		if (responseJson['errcode'] == 0):
			self.logger.fileInfoLogger.info("Time : %f, successfully send message to %s" % (time.time(), userID))
			return True
		else:
			self.logger.fileInfoLogger.error(
				"Time: %f, failed to send message, reason: %s" % (time.time(), responseJson['errmsg']))
			emailController = Email.EmailController()
			emailController.sendEmail(msgStr="发送模版消息失败，原因是 %s ，位于Api.py line 114" % (responseJson['errmsg']),
									  subject="发送模版消息失败", withLog=False)
			return None

	# 检查token是否超过有效期-辅助函数，不需直接调用
	def isAccessTokenOutOfDate(self, validTime=-1.0, lastRequired=0.0):
		timeGap = time.time() - lastRequired
		return validTime <= timeGap


if __name__ == "__main__":
	api = WechatApi()
	url = "http://weixin.qq.com/download"

	openid = api.config.getConfig(sectionName='WECHAT',
								  optionName='OPENID_YL')
	templateID = api.config.getConfig(sectionName='WECHAT',
									  optionName='TEMPLATE_ID')
	data = {
		"first": {
			"value": "你好，你有一条新的上线消息，敬请查收",
			"color": "#173177"
		},
		"keyword1": {
			"value": "test_userid",
			"color": "#173177"
		},
		"keyword2": {
			"value": "test_username",
			"color": "#173177"
		},
		"keyword3": {
			"value": "有线登陆",
			"color": "#173177"
		},
		"keyword4": {
			"value": "北洋园校区",
			"color": "#173177"
		},
		"keyword5": {
			"value": "2.5GB",
			"color": "#173177"
		},
		"remark": {
			"value": "如非本人登录，请尽快处理。",
			"color": "#173177"
		}
	}
	print(api.sendOnLineNotice(userID='test_userid',
							   openID=openid,
							   templateID=templateID,
							   data=data,
							   url=url))
# print(api.getAllTemplate())
